/**
 * 
 */
package ro.dta.idbi.ui.patterns;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTextField;

import ro.dta.idbi.interfaces.ITransformationResult;
import ro.dta.idbi.interfaces.sql.ISqlConstruct;
import ro.dta.idbi.interfaces.ui.IMainFrame;
import ro.dta.idbi.interfaces.ui.ITransformationDialog;
import ro.dta.idbi.model.AbstractPattern;
import ro.dta.idbi.model.TransformationResult;
import uk.ac.ic.doc.automed.reps.Schema;

/**
 * Abstract transformation dialog for applying a transformation pattern over a
 * given schema
 * 
 * @author Tudor Dobrila
 * 
 */
public abstract class AbstractPatternDialog extends JDialog implements ITransformationDialog {

	private static final long serialVersionUID = -1106141325025167723L;

	/**
	 * Element over which the transformatin is applied
	 */
	protected transient ISqlConstruct[] element;

	/**
	 * Parent frame of the dialog
	 */
	protected transient IMainFrame parentFrame;

	/**
	 * Original schema over which the transformation is applied
	 */
	protected transient Schema schema;

	/**
	 * Transformation result
	 */
	protected transient ITransformationResult transResult;

	/**
	 * Split pane containing the before and after diagrams
	 */
	protected transient JSplitPane splitPane;

	/**
	 * Text field containing the equivalent command call for this transformation
	 */
	protected transient JTextField macroField;

	/**
	 * Apply transformation button
	 */
	protected transient JButton confirmBtn;

	/**
	 * Panel in the center of the dialog
	 */
	protected transient JPanel centerPanel;

	/**
	 * Transformation Dialog class construct
	 * 
	 * @param parentFrame
	 *            Parent frame of this dialog
	 * @param schema
	 *            Schema over which the transformation is applied
	 * @param element
	 *            Sql construct(s) over which the transformation is applied
	 * @param beforeLabel
	 *            Label for the before diagram
	 * @param afterLabel
	 *            Label for the transformed diagram
	 */
	public AbstractPatternDialog(final IMainFrame parentFrame, final Schema schema,
			final ISqlConstruct[] element, final JLabel beforeLabel, final JLabel afterLabel) {
		super();
		setSize(700, 400);
		if (element.length == 1) {
			setTitle("Transform element " + element[0].getSchemaObject().getValue() + " in schema "
					+ schema.getName());
		} else {
			setTitle("Transform elements in schema " + schema.getName());
		}
		setModal(true);
		setLocationRelativeTo(null);
		setIconImage(parentFrame.getIconImage());
		
		this.parentFrame = parentFrame;
		this.schema = schema;
		this.element = new ISqlConstruct[element.length];
		this.confirmBtn = new JButton("Apply transformation");
		this.macroField = new JTextField();
		System.arraycopy(element, 0, this.element, 0, element.length);
		this.centerPanel = new JPanel(new GridBagLayout());
		
		final GridBagConstraints constr = new GridBagConstraints();
		constr.fill = GridBagConstraints.BOTH;

		splitPane = new JSplitPane();
		splitPane.setDividerLocation(250);
		constr.gridx = 0;
		constr.gridy = 0;
		constr.weightx = 1.0;
		constr.weighty = 1.0;
		centerPanel.add(splitPane, constr);

		// Create left view containing the original diagram
		final JPanel leftPanel = new JPanel(new GridBagLayout());
		final GridBagConstraints constr1 = new GridBagConstraints();
		constr1.fill = GridBagConstraints.BOTH;

		if (beforeLabel != null) {
			constr1.gridx = 0;
			constr1.gridy = 0;
			constr1.weightx = 1.0;
			constr1.weighty = 0.0;
			constr1.ipady = 20;
			leftPanel.add(beforeLabel, constr1);
		}

		final JComponent left = createOriginalDiagram();
		if (left != null) {
			constr1.gridx = 0;
			constr1.gridy = 1;
			constr1.weightx = 1.0;
			constr1.weighty = 1.0;
			constr1.ipady = 0;
			leftPanel.add(left, constr1);
		}
		splitPane.setLeftComponent(leftPanel);

		// Create right view containing the transformed diagram
		final JPanel rightPanel = new JPanel(new GridBagLayout());
		final GridBagConstraints constr2 = new GridBagConstraints();
		constr2.fill = GridBagConstraints.BOTH;

		if (afterLabel != null) {
			constr2.gridx = 0;
			constr2.gridy = 0;
			constr2.weightx = 1.0;
			constr2.weighty = 0.0;
			constr2.ipady = 20;
			rightPanel.add(afterLabel, constr2);
		}

		final JComponent right = createTransformedDiagram();
		if (right != null) {
			constr2.gridx = 0;
			constr2.gridy = 1;
			constr2.weightx = 1.0;
			constr2.weighty = 1.0;
			constr2.ipady = 0;
			rightPanel.add(right, constr2);
		}

		splitPane.setRightComponent(rightPanel);

		// Create the equvalent command label & text field
		final JLabel macroLabel = new JLabel("Equivalent command :");
		constr.gridx = 0;
		constr.gridy = 1;
		constr.weightx = 1.0;
		constr.weighty = 0.0;
		constr.insets = new Insets(3, 3, 3, 3);
		centerPanel.add(macroLabel, constr);

		constr.gridx = 0;
		constr.gridy = 2;
		constr.weightx = 1.0;
		constr.weighty = 0.0;
		constr.insets = new Insets(3, 3, 3, 3);
		macroField.setEditable(false);
		centerPanel.add(macroField, constr);

		constr.fill = GridBagConstraints.NONE;
		constr.gridx = 0;
		constr.gridy = 3;
		constr.weightx = 1.0;
		constr.weighty = 0.0;
		confirmBtn.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(final ActionEvent event) {
				try {
					final String command = macroField.getText();
					final Schema transSchema = AbstractPattern.execute(
							AbstractPatternDialog.this.schema, command);

					if (transSchema == null) {
						JOptionPane
								.showMessageDialog(
										AbstractPatternDialog.this,
										"Could not execute command!\r\nReason: Definition for this transformation does not exist",
										"Error", JOptionPane.ERROR_MESSAGE);
					} else {
						transResult = new TransformationResult(schema, transSchema, command);
						final String name = transSchema.getName();
						parentFrame.getRepositoryBrowser().refresh();
						parentFrame.getRepositoryBrowser().select(name);
						parentFrame
								.setStatusBarText("Transformation applied successfully. New schema: "
										+ name);
						setVisible(false);
					}
				} catch (Exception e1) {
					JOptionPane.showMessageDialog(AbstractPatternDialog.this,
							"Could not execute command!\r\nReason: " + e1.getMessage(), "Error",
							JOptionPane.ERROR_MESSAGE);
				}

			}
		});
		centerPanel.add(confirmBtn, constr);

		getContentPane().add(centerPanel, BorderLayout.CENTER);
	}

	/**
	 * Create the left (original) diagram
	 */
	protected abstract JComponent createOriginalDiagram();

	/**
	 * Create the right (transformed) diagram
	 */
	protected abstract JComponent createTransformedDiagram();

	/*
	 * (non-Javadoc)
	 * 
	 * @see ro.dta.idbi.ui.patterns.ITransformationDialog#getResult()
	 */
	@Override
	public ITransformationResult getResult() {
		return transResult;
	}
}
